home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / unarced / utilities / system / intuition / shadow / examples / gui / gui.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-17  |  25.9 KB  |  863 lines

  1. /*
  2.  * First run attempt at a functional GUI library.
  3.  * I agree, it sucks, but it's good enough, as Americans USED to
  4.  *  say.
  5.  *
  6.  * (C) CopyRight 1991 by David C. Navas
  7.  */
  8. #include "gui.h"
  9.  
  10. #include <libraries/diskfont.h>
  11. #include <proto/diskfont.h>
  12. #include <proto/graphics.h>
  13. #include <shadow/coreRoot.h>
  14. #include <shadow/coreMeta.h>
  15. #include <shadow/misc.h>
  16. #include <shadow/process.h>
  17. #include <shadow/semaphore.h>
  18. #include <shadow/shadowBase.h>
  19. #include <shadow/shadow_proto.h>
  20. #include <shadow/shadow_pragmas.h>
  21.  
  22. #include <dos/dostags.h>
  23. #include <ipc.h>
  24. #include <ipc_proto.h>
  25.  
  26. extern struct ExecBase * __far SysBase;
  27. struct GadToolsBase * __far GadToolsBase;
  28. struct IntuitionBase * __far IntuitionBase;
  29. extern struct DiskfontBase * __far DiskFontBase;
  30. extern struct GfxBase * __far GfxBase;
  31. extern struct ShadowBase * __far ShadowBase;
  32.  
  33. /*
  34.  * external class definitions.
  35.  */
  36. extern char GuiProcClassName[],
  37.             GuiTaskName[],
  38.             GuiClassName[],
  39.             WindowClassName[],
  40.             GadgTClassName[];
  41.  
  42. void RemoveWinSafely(struct Window *win);
  43. void StripIntuiMessages(struct MsgPort *port, struct Window *win);
  44.  
  45. extern struct SignalSemaphore programSemaphore;
  46.  
  47. struct TextAttr __far ta = {"topaz.font", 11, FS_NORMAL,
  48.                             FPF_ROMFONT | FPF_DISKFONT};
  49. struct TextFont * __far tf;
  50.  
  51. /*
  52.  * ==========================================================================
  53.  * =                                                                        =
  54.  * =           Class definition for the GUI process.                        =
  55.  * =                                                                        =
  56.  * ==========================================================================
  57.  */
  58. ATTRIBUTE_TAG guiProcAttrs[] =
  59.                         {
  60.                            ATTR_GUIPROCESS, sizeof(struct GuiProcess), NULL,
  61.                            TAG_END
  62.                         };
  63.  
  64. /*
  65.  * ==========================================================================
  66.  * =                                                                        =
  67.  * =           Class definition for GUI type of objects.                    =
  68.  * =                                                                        =
  69.  * ==========================================================================
  70.  */
  71.  
  72. ATTRIBUTE_TAG guiAttrs[] =
  73.                         {
  74.                            ATTR_GUICHILDREN, FLAG_ATTR_WATCHED | SHADOW_BINTREE,
  75.                                              NULL,
  76.                            ATTR_GUISTRUCT, sizeof(struct GUIStruct), NULL,
  77.                            ATTR_GUIOUTPUT, sizeof(struct OutputStruct), NULL,
  78.                            TAG_END
  79.                         };
  80. METHOD_TAG guiMethods[] =
  81.                         {
  82.                            {
  83.                               METHOD_META_REMOVE,
  84.                               NULL, NULL,
  85.                               SHADOW_MSG_SYNC,
  86.                               METHOD_FLAG_PROC, 0,
  87.                               (METHODFUNCTYPE)GuiRemoveMethod, NULL
  88.                            },
  89.                            {
  90.                               METHOD_META_DESTROY,
  91.                               NULL, NULL,
  92.                               SHADOW_MSG_SYNC,
  93.                               METHOD_FLAG_PROC, 0,
  94.                               (METHODFUNCTYPE)GuiDestroyMethod, NULL
  95.                            },
  96.                            {
  97.                               METHOD_META_INIT,
  98.                               NULL, NULL,
  99.                               SHADOW_MSG_SYNC,
  100.                               METHOD_FLAG_PROC, 0,
  101.                               GuiInitMethod, REF_GuiInitMethod
  102.                            },
  103.                            TAG_END
  104.                         };
  105.  
  106. /*
  107.  * ==========================================================================
  108.  * =                                                                        =
  109.  * =           Class definition for window objects.                         =
  110.  * =                                                                        =
  111.  * ==========================================================================
  112.  */
  113.  
  114. ATTRIBUTE_TAG winAttrs[] =
  115.                         {
  116.                            ATTR_WINDOW, sizeof(struct WindowObject), NULL,
  117.                            TAG_END
  118.                         };
  119. METHOD_TAG winMethods[] =
  120.                         {
  121.                            {
  122.                               METHOD_META_INIT,
  123.                               NULL, NULL,
  124.                               SHADOW_MSG_SYNC,
  125.                               METHOD_FLAG_PROC, 0,
  126.                               WinOpenMethod, REF_WinOpenMethod
  127.                            },
  128.                            {
  129.                               METHOD_META_DESTROY,
  130.                               NULL, NULL,
  131.                               SHADOW_MSG_SYNC,
  132.                               METHOD_FLAG_PROC, 0,
  133.                               (METHODFUNCTYPE)WinDestroyMethod, NULL
  134.                            },
  135.                            {
  136.                               METHOD_WINDOW_CLOSE,
  137.                               NULL, NULL,
  138.                               SHADOW_MSG_SYNC,
  139.                               METHOD_FLAG_PROC, 0,
  140.                               (METHODFUNCTYPE)WinCloseMethod, NULL
  141.                            },
  142.                            TAG_END
  143.                         };
  144.  
  145. /*
  146.  * ==========================================================================
  147.  * =                                                                        =
  148.  * =           Class definition for gadget objects.                         =
  149.  * =                                                                        =
  150.  * ==========================================================================
  151.  */
  152.  
  153. ATTRIBUTE_TAG gadAttrs[] =
  154.                         {
  155.                             ATTR_GADGET, sizeof(struct GadgetObject), NULL,
  156.                             TAG_END
  157.                         };
  158.  
  159. METHOD_TAG gadMethods[] =
  160.                         {
  161.                            {
  162.                               METHOD_META_INIT,
  163.                               NULL, NULL,
  164.                               SHADOW_MSG_SYNC,
  165.                               METHOD_FLAG_PROC, 0,
  166.                               GadgTOpenMethod, REF_GadgTOpenMethod
  167.                            },
  168.                            {
  169.                               METHOD_GADGET_CHANGE,
  170.                               NULL, NULL,
  171.                               SHADOW_MSG_SYNC,
  172.                               METHOD_FLAG_PROC, 0,
  173.                               (METHODFUNCTYPE)GadgTChangeMethod,
  174.                                  REF_GadgTChangeMethod
  175.                            },
  176.                            TAG_END
  177.                         };
  178.  
  179.  
  180. /*
  181.  * ==========================================================================
  182.  * =                                                                        =
  183.  * =                 Initialize these classes                               =
  184.  * =                                                                        =
  185.  * ==========================================================================
  186.  */
  187.  
  188. void geta4(void);
  189.  
  190. BOOL InitGUISystem(void)
  191. {
  192.    OBJECT guiTask;
  193.    BOOL   success;
  194.  
  195.    if (!(DiskfontBase = OpenLibrary("diskfont.library", 0)))
  196.       return FALSE;
  197.  
  198.    if (!(GfxBase = OpenLibrary("graphics.library", 0)))
  199.    {
  200.       return FALSE;
  201.    }
  202.    if (!(tf = OpenDiskFont(&ta)))
  203.    {
  204.       VPrintf("couldn't find font\n", NULL);
  205.       return FALSE;
  206.    }
  207.  
  208.    /*
  209.     * Create the guiProcess CLass.
  210.     */
  211.    success = AddAutoResource(NULL,
  212.                              CreateSubClass(NULL,
  213.                                             PROCESSCLASS,
  214.                                             METACLASS,
  215.                                             GuiProcClassName,
  216.                                             NULL,
  217.                                             guiProcAttrs,
  218.                                             NULL,
  219.                                             METHOD_END),
  220.                              GuiProcClassName);
  221.  
  222.    /*
  223.     * Create the guiTask
  224.     */
  225.    {
  226.       struct TagItem tag[4];
  227.  
  228.       tag[0].ti_Tag = NP_Priority;
  229.       tag[0].ti_Data = 1;
  230.       tag[1].ti_Tag = NP_StackSize;
  231.       tag[1].ti_Data = 6000;
  232.       tag[2].ti_Tag = NP_Output;
  233.       tag[2].ti_Data = (ULONG)Open("CONSOLE:", MODE_OLDFILE);
  234.       tag[3].ti_Tag = TAG_END;
  235.  
  236.       guiTask = CreateInstance(NULL,
  237.                                GuiProcClassName,
  238.                                METACLASS,
  239.                                GuiTaskName,
  240.                                GUIThreadStart,
  241.                                &programSemaphore,
  242.                                tag,
  243.                                METHOD_END);
  244.       if (tag[2].ti_Tag != TAG_IGNORE)
  245.          Close(tag[2].ti_Data);
  246.    }
  247.  
  248.    SetupMethodTags(guiMethods, guiTask, (void *)-1);
  249.    SetupMethodTags(winMethods, guiTask, (void *)-1);
  250.    SetupMethodTags(gadMethods, guiTask, (void *)-1);
  251.  
  252.    success &= AddAutoResource(NULL,
  253.                               CreateSubClass(NULL,
  254.                                              ROOTCLASS,
  255.                                              METACLASS,
  256.                                              GuiClassName,
  257.                                              NULL,
  258.                                              guiAttrs,
  259.                                              guiMethods,
  260.                                              METHOD_END),
  261.                               GuiClassName);
  262.  
  263.    success &= AddAutoResource(NULL,
  264.                               CreateSubClass(NULL,
  265.                                              GuiClassName,
  266.                                              METACLASS,
  267.                                              WindowClassName,
  268.                                              NULL,
  269.                                              winAttrs,
  270.                                              winMethods,
  271.                                              METHOD_END),
  272.                               WindowClassName);
  273.  
  274.    success &= AddAutoResource(NULL,
  275.                               CreateSubClass(NULL,
  276.                                              GuiClassName,
  277.                                              METACLASS,
  278.                                              GadgTClassName,
  279.                                              NULL,
  280.                                              gadAttrs,
  281.                                              gadMethods,
  282.                                              METHOD_END),
  283.                               GadgTClassName);
  284.  
  285.    success &= AddAutoResource(NULL, guiTask, GuiTaskName);
  286.  
  287.    return success;
  288. }
  289.  
  290. /*
  291.  ==========================================================================
  292.                            gui task
  293.  ==========================================================================
  294.  */
  295.  
  296. /*
  297.  * First, define the GUI Process Class
  298.  */
  299.  
  300. void GUIThreadStart()
  301. {
  302.    struct Task *task;
  303.    struct JazzProcess *jproc;
  304.    struct GuiProcess *gui;
  305.    struct IPCPort *port, *replyPort;
  306.    struct MsgPort *guiPort;
  307.  
  308.    /*
  309.     * THE main EVENT LOOP!!!!
  310.     */
  311.  
  312.    geta4();
  313.  
  314. #ifndef  NDEBUG
  315.    VPrintf("GUI system startup\n", NULL);
  316. #endif
  317.    task = WaitThread();
  318.  
  319.    jproc = FindAttribute(task->tc_UserData, ATTR_JAZZPROCESS);
  320.  
  321.    gui = FindAttribute(task->tc_UserData, ATTR_GUIPROCESS);
  322.  
  323.    if (!(IntuitionBase = OpenLibrary("intuition.library", 36)))
  324.    {
  325.       DoJazzMethod((OBJECT)task->tc_UserData, NULL,
  326.                    METHOD_META_REMOVE, METHOD_END);
  327.       Signal(jproc->jp_parent, 1L << jproc->jp_parentSignal);
  328.       return;
  329.    }
  330.  
  331.    if (!(GadToolsBase = OpenLibrary("gadtools.library", 36)))
  332.    {
  333.       DoJazzMethod((OBJECT)task->tc_UserData, NULL,
  334.                    METHOD_META_REMOVE, METHOD_END);
  335.       CloseLibrary(IntuitionBase);
  336.       Signal(jproc->jp_parent, 1L << jproc->jp_parentSignal);
  337.       return;
  338.    }
  339.    if (!(gui->guip_port = guiPort = CreateMsgPort()))
  340.    {
  341.       DoJazzMethod((OBJECT)task->tc_UserData, NULL,
  342.                    METHOD_META_REMOVE, METHOD_END);
  343.       CloseLibrary(GadToolsBase);
  344.       CloseLibrary(IntuitionBase);
  345.       Signal(jproc->jp_parent, 1L << jproc->jp_parentSignal);
  346.       return;
  347.    }
  348.    if (!(task = InitThread(task)))
  349.    {
  350.       CLASS root;
  351.  
  352.       DeleteMsgPort(guiPort);
  353.       CloseLibrary(GadToolsBase);
  354.       CloseLibrary(IntuitionBase);
  355.  
  356.       task = FindTask(NULL);
  357.  
  358.       do
  359.          Wait(SIGBREAKF_CTRL_C);
  360.       while(jproc->jp_parent);
  361.  
  362.       QuickDropString(jproc->jp_procName);
  363.       root = FindJazzClass(ROOTCLASS);
  364.       DoJazzMethod((OBJECT)task->tc_UserData,
  365.                    root, METHOD_META_DESTROY, METHOD_END);
  366.       DropObject(root);
  367.       return;
  368.    }
  369.  
  370.    port = jproc->jp_port;
  371.    replyPort = jproc->jp_replyPort;
  372.  
  373.    while(TRUE)
  374.    {
  375.       struct IPCMessage *msg;
  376.       struct IntuiMessage *intui;
  377.       ULONG signals;
  378.  
  379.       signals = Wait( SigBitIPCPort(port) |
  380.                       SigBitIPCPort(replyPort) |
  381.                       (1L << guiPort->mp_SigBit) |
  382.                       SIGBREAKF_CTRL_C);
  383.  
  384.       while(msg = GetIPCMessage(port))
  385.          ParseJazzMessage(msg);
  386.       while(msg = GetIPCMessage(replyPort))
  387.          JunkIPCMessage(msg);
  388.       while(intui = GT_GetIMsg(guiPort))
  389.          HandleIntuiMessage(intui);
  390.  
  391.       if (signals & SIGBREAKF_CTRL_C)
  392.       {
  393.          if (jproc->jp_parent)
  394.          {
  395. #ifndef  NDEBUG
  396.             VPrintf("I was signalled?\n", NULL);
  397. #endif
  398.             continue;
  399.          } else
  400.          {
  401.             DeleteMsgPort(guiPort);
  402.  
  403.             RemoveThread(task->tc_UserData);
  404.  
  405.             CloseLibrary(GadToolsBase);
  406.             CloseLibrary(IntuitionBase);
  407.             if (tf)  CloseFont(tf);
  408.             if (DiskfontBase)
  409.                CloseLibrary(DiskfontBase);
  410.             if (GfxBase)
  411.                CloseLibrary(GfxBase);
  412.             return;
  413.          }
  414.       }
  415.    }
  416. }
  417.  
  418. /*
  419.  *
  420.  * GUI CLASS METHODS
  421.  *
  422.  */
  423. METHOD_REF REF_GuiInitMethod[] = {
  424.                                     {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  425.                                     {'JSTR', sizeof(char *), 0},
  426.                                     {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  427.                                     {'JSTR', sizeof(char *), 0},
  428.                                     {TAG_END, SHADOW_RETURN_OBJECT, 0}
  429.                                  };
  430.  
  431. void *GuiInitMethod(METHOD_ARGS, OBJECT parent,
  432.                                  char *name,
  433.                                  OBJECT out_object,
  434.                                  char *out_method)
  435. {
  436.    W_AVLTREE Wtree;
  437.    struct GUIStruct *gui;
  438.    struct OutputStruct *io;
  439.  
  440.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  441.    gui->gui_parent = parent;
  442.  
  443.    if (parent)
  444.       Wtree = FindAttribute(parent, ATTR_GUICHILDREN);
  445.  
  446.    io = FindAttribute(object, ATTR_GUIOUTPUT);
  447.    io->out_object = out_object;
  448.  
  449.    UseObject(object);
  450.    UseObject(parent);
  451.    UseObject(out_object);
  452.  
  453.    if (!name || (name = UseString(name)))
  454.    {
  455.       gui->gui_moniker = name;
  456.       if (!out_method || (out_method = UseString(out_method)))
  457.       {
  458.          io->out_method = out_method;
  459.          if (!parent || AddNodeStringWatchedBinTree(Wtree, object, name))
  460.          {
  461.             if(DoJazzMethod(object, class->meta_superClass, MethodID, METHOD_END))
  462.             {
  463.  
  464.                DropObject(object);
  465.                return object;
  466.             }
  467.             if (parent) RemoveStringWatchedBinNode(Wtree, object, name);
  468.          }
  469.          DropString(out_method);
  470.       }
  471.       DropString(name);
  472.    }
  473.    DropObject(object);
  474.    return NULL;
  475. }
  476.  
  477. /*
  478.  * Watch the semaphores!
  479.  */
  480.  
  481. void GuiRemoveMethod(METHOD_ARGS)
  482. {
  483.    struct GUIStruct *gui;
  484.    struct OutputStruct *io;
  485.    W_AVLTREE children;
  486.    OBJECT    parent;
  487.  
  488.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  489.    io = FindAttribute(object, ATTR_GUIOUTPUT);
  490.  
  491.    PSem(object, SHADOW_EXCLUSIVE_SEMAPHORE);
  492.  
  493.    DropObject(io->out_object);
  494.    QuickDropString(io->out_method);
  495.  
  496.    parent = gui->gui_parent;
  497.    gui->gui_parent = io->out_object = NULL;
  498.    io->out_method = NULL;
  499.  
  500.    VSem(object);
  501.  
  502.    children = FindAttribute(object, ATTR_GUICHILDREN);
  503.    PSem(&children->wv_value, SHADOW_EXCLUSIVE_SEMAPHORE);
  504.    while(children->wv_value)
  505.    {
  506.       OBJECT gadgetObject;
  507.  
  508.       gadgetObject = UseObject((void *)children->wv_value->bn_value);
  509.       VSem(&children->wv_value);
  510.       DoJazzMethod(gadgetObject, NULL, METHOD_META_REMOVE, METHOD_END);
  511.       DropObject(gadgetObject);
  512.       PSem(&children->wv_value, SHADOW_EXCLUSIVE_SEMAPHORE);
  513.    }
  514.  
  515.    VSem(&children->wv_value);
  516.  
  517.    /*
  518.     * remove object from parent list.
  519.     */
  520.    if (parent)
  521.    {
  522.       /*
  523.        * Ignore misnomer, please.
  524.        * Actually, fellow sblings.
  525.        */
  526.       children = FindAttribute(parent, ATTR_GUICHILDREN);
  527.       RemoveStringWatchedBinNode(children, object, gui->gui_moniker);
  528.    }
  529.  
  530.    CallSuper();
  531.    DropObject(parent);
  532. }
  533.  
  534. void GuiDestroyMethod(METHOD_ARGS)
  535. {
  536.    struct GUIStruct *gui;
  537.  
  538.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  539.    QuickDropString(gui->gui_moniker);
  540.    CallSuper();
  541. }
  542.  
  543. /*
  544.  *
  545.  * WINDOW CLASS METHODS
  546.  *
  547.  */
  548.  
  549.  
  550. /*
  551.  * METHOD_META_INIT
  552.  */
  553. METHOD_REF  REF_WinOpenMethod[] = {
  554.                                      {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  555.                                      {'JSTR', sizeof(char *), 0},
  556.                                      {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  557.                                      {'JSTR', sizeof(char *), 0},
  558.                                      {'TAGL', sizeof(void *),
  559.                                               sizeof(struct TagItem)},
  560.                                      {TAG_END, SHADOW_RETURN_OBJECT, 0}
  561.                                   };
  562.  
  563. void *WinOpenMethod(METHOD_ARGS, OBJECT parent,
  564.                                  char *name,
  565.                                  OBJECT out_object,
  566.                                  char *out_method,
  567.                                  struct TagItem *tags)
  568. {
  569.    struct WindowObject *wobj;
  570.  
  571.    UseObject(object);
  572.    wobj = FindAttribute(object, ATTR_WINDOW);
  573.    name = UseString(name);
  574.  
  575.    if (wobj->wo_window = OpenWindowTags(NULL, WA_Flags, 0xf,
  576.                                            WA_Title, name,
  577.                                            TAG_MORE, tags))
  578.    {
  579.       struct GuiProcess *gui;
  580.  
  581.       gui = FindAttribute(FindTask(NULL)->tc_UserData, ATTR_GUIPROCESS);
  582.  
  583.       wobj->wo_window->UserPort = gui->guip_port;
  584.       wobj->wo_window->UserData = (void *)object;
  585.  
  586.       /*
  587.        * Would require V37 to check ModifyIDCMP!
  588.        */
  589.  
  590.       ModifyIDCMP(wobj->wo_window, LISTVIEWIDCMP | CLOSEWINDOW | REFRESHWINDOW);
  591.  
  592.       {
  593.          if (wobj->wo_vi = GetVisualInfo(wobj->wo_window->WScreen, TAG_END))
  594.          {
  595.             if (wobj->wo_lastGadget = CreateContext(&wobj->wo_rootGadget))
  596.             {
  597.                AddGList(wobj->wo_window, wobj->wo_rootGadget, -1, -1, NULL);
  598.  
  599.                /*
  600.                 * Force tags to NULL -- ick, I hate optimizers.
  601.                 */
  602.  
  603.                ForceMethodEnd(out_method);
  604.  
  605.                if (CallSuper())
  606.                {
  607.                   /*
  608.                    * Used twice, once for return, once in window structure.
  609.                    */
  610.  
  611.                   /*
  612.                    * Name is in superClass under gui->gui_moniker
  613.                    */
  614.                   DropString(name);
  615.                   return object;
  616.                }
  617.             }
  618.          }
  619.       }
  620.       DropString(name);
  621.       DoJazzMethod(object, NULL, METHOD_WINDOW_CLOSE, METHOD_END);
  622.       return NULL;
  623.    }
  624.    DropString(name);
  625.    DropObject(object);
  626.    return NULL;
  627. }
  628.  
  629. void WinDestroyMethod(METHOD_ARGS)
  630. {
  631.    struct WindowObject *wobj;
  632.  
  633.    wobj = FindAttribute(object, ATTR_WINDOW);
  634.  
  635.    if (wobj->wo_window)
  636.       CloseWindow(wobj->wo_window);
  637.    FreeVisualInfo(wobj->wo_vi);
  638.  
  639.    if (wobj->wo_rootGadget)
  640.       FreeGadgets(wobj->wo_rootGadget);
  641.  
  642.    CallSuper();
  643. }
  644.  
  645. void WinCloseMethod(METHOD_ARGS)
  646. {
  647.    struct WindowObject *wobj;
  648.    struct Window *window;
  649.  
  650.    wobj = FindAttribute(object, ATTR_WINDOW);
  651.  
  652.    /*
  653.     * Should remove all child gadgets.
  654.     */
  655.  
  656.    if (window = wobj->wo_window)
  657.    {
  658.       RemoveGList(window, wobj->wo_rootGadget, -1);
  659.       RemoveWinSafely(window);      /* Unuses object from UserData field */
  660.    }
  661.    CallSuper();
  662. }
  663.  
  664. /*
  665.  *
  666.  * GADGT METHODS
  667.  *
  668.  */
  669.  
  670. METHOD_REF REF_GadgTOpenMethod[] =
  671.                                     {
  672.                                        'JOBJ', sizeof(OBJECT),
  673.                                                SHADOW_OBJECT,
  674.                                        'JSTR', sizeof(char *), 0,
  675.                                        'JOBJ', sizeof(void *),
  676.                                                SHADOW_OBJECT,
  677.                                        'JSTR', sizeof(char *), 0,
  678.                                        'NGAD', sizeof(struct NewGadget *),
  679.                                                sizeof(struct NewGadget),
  680.                                        'type', sizeof(long), 0,
  681.                                        'TAGL', sizeof(void *),
  682.                                                sizeof(struct TagItem),
  683.                                        {TAG_END, SHADOW_RETURN_OBJECT, 0}
  684.                                     };
  685.  
  686. void *GadgTOpenMethod(METHOD_ARGS, OBJECT window,
  687.                                    char *name,
  688.                                    OBJECT out_object,
  689.                                    char *out_method,
  690.                                    struct NewGadget *ng,
  691.                                    long gadType,
  692.                                    struct TagItem *tags)
  693. {
  694.    struct GadgetObject *gobj;
  695.    struct WindowObject *windowObj;
  696.  
  697.    UseObject(object);
  698.    if (!window || !ng)
  699.    {
  700.       DropObject(object);
  701.       return NULL;
  702.    }
  703.  
  704.    gobj = FindAttribute(object, ATTR_GADGET);
  705.    if (!(windowObj = FindAttribute(window, ATTR_WINDOW)))
  706.    {
  707.       DropObject(object);
  708.       return NULL;
  709.    }
  710.  
  711.    ng->ng_TextAttr = &ta;
  712.    ng->ng_VisualInfo = windowObj->wo_vi;
  713.    ng->ng_UserData = object;
  714.    ng->ng_GadgetText = UseString(name);
  715.  
  716.    RemoveGList(windowObj->wo_window, windowObj->wo_rootGadget, -1);
  717.  
  718.    if (gobj->go_gadget = CreateGadgetA(gadType, windowObj->wo_lastGadget, ng, tags))
  719.    {
  720.       AddGList(windowObj->wo_window, windowObj->wo_rootGadget, -1, -1, NULL);
  721.  
  722.       ForceMethodEnd(ng);
  723.       if (CallSuper())
  724.       {
  725.          RefreshGList(windowObj->wo_lastGadget, windowObj->wo_window, NULL, ((UWORD)-1));
  726.          windowObj->wo_lastGadget = gobj->go_gadget;
  727.  
  728.          GT_RefreshWindow(windowObj->wo_window, NULL);
  729.  
  730.          /*
  731.           * name used by superClass, can drop it here.
  732.           * Otherwise would have to subclass METHOD_DESTROY, which would suck.
  733.           */
  734.          DropString(name);
  735.          DropObject(object);
  736.          return object;
  737.       }
  738.    } else
  739.       AddGList(windowObj->wo_window, windowObj->wo_rootGadget, -1, -1, NULL);
  740.    DropObject(object);
  741.    return NULL;
  742. }
  743.  
  744. METHOD_REF REF_GadgTChangeMethod[] =
  745.                                     {
  746.                                        'TAGL', sizeof(void *),
  747.                                                sizeof(struct TagItem),
  748.                                        TAG_END
  749.                                     };
  750. void GadgTChangeMethod(METHOD_ARGS, struct TagItem *tags)
  751. {
  752.    struct GadgetObject *gobj;
  753.    struct GUIStruct *gui;
  754.    struct WindowObject *windowObj;
  755.  
  756.    gobj = FindAttribute(object, ATTR_GADGET);
  757.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  758.    windowObj = FindAttribute(gui->gui_parent, ATTR_WINDOW);
  759.  
  760.    GT_SetGadgetAttrsA(gobj->go_gadget, windowObj->wo_window, NULL, tags);
  761. }
  762.  
  763. /*
  764.  ==============================================================================
  765.  =                                                                            =
  766.  =                            SUPPLEMENTARY                                   =
  767.  =                                                                            =
  768.  ==============================================================================
  769.  */
  770. void HandleIntuiMessage(struct IntuiMessage *intui)
  771. {
  772.    switch(intui->Class) {
  773.       OBJECT winObject;
  774.  
  775.       case CLOSEWINDOW:
  776.          winObject = (void *)intui->IDCMPWindow->UserData;
  777.          GT_ReplyIMsg(intui);
  778.          UseObject(winObject);
  779.          DoJazzMethod(winObject, NULL, METHOD_WINDOW_CLOSE, METHOD_END);
  780.          DropObject(winObject);
  781.          break;
  782. /*
  783.       case MOUSEBUTTONS:
  784.          if(msg->Code == SELECTDOWN)
  785.             handler = mouseHandlers.push;
  786.          else handler = mouseHandlers.release;
  787.          break;
  788.       case MOUSEMOVE:
  789.          if(msg->Qualifier & IEQUALIFIER_LEFTBUTTON)
  790.          handler = mouseHandlers.move;
  791.          break;
  792. */
  793.       case REFRESHWINDOW:
  794.          winObject = (void *)intui->IDCMPWindow->UserData;
  795.          UseObject(winObject);
  796.  
  797.          GT_BeginRefresh(intui->IDCMPWindow);
  798.          DoJazzMethod((void *)intui->IDCMPWindow->UserData, NULL,
  799.                       METHOD_WINDOW_REFRESH, METHOD_END);
  800.          GT_EndRefresh(intui->IDCMPWindow, TRUE);
  801.          GT_ReplyIMsg(intui);
  802.          DropObject(winObject);
  803.          break;
  804.  
  805.       case GADGETUP:
  806.          {
  807.             struct OutputStruct *io;
  808.             OBJECT object;
  809.  
  810.             io = FindAttribute(((struct Gadget *)intui->IAddress)->UserData,
  811.                                ATTR_GUIOUTPUT);
  812.             UseObject(object = io->out_object);
  813.             GT_ReplyIMsg(intui);
  814.             DoJazzMethod(object, NULL, io->out_method, (void *)intui->Code,
  815.                                                        METHOD_END);
  816.             DropObject(object);
  817.          }
  818.          break;
  819.       default:
  820.          GT_ReplyIMsg(intui);
  821.          break;
  822.   }
  823. }
  824.  
  825. void RemoveWinSafely(struct Window *win)
  826. {
  827.    void *object;
  828.  
  829.    object = win->UserData;
  830.    if (win->UserPort)
  831.    {
  832.       Forbid();
  833.       StripIntuiMessages(win->UserPort, win);
  834.       win->UserPort = NULL;
  835.       ModifyIDCMP(win, NULL);
  836.       win->UserData = NULL;
  837.       Permit();
  838.  
  839.       /*
  840.        * stop using this object in window structure.
  841.        */
  842.       DropObject(object);
  843.    }
  844. }
  845.  
  846. void StripIntuiMessages(struct MsgPort *port, struct Window *win)
  847. {
  848.    struct IntuiMessage *msg;
  849.    struct Node *succ;
  850.  
  851.    msg = (struct IntuiMessage *)port->mp_MsgList.lh_Head;
  852.  
  853.    while(succ = msg->ExecMessage.mn_Node.ln_Succ)
  854.    {
  855.       if (msg->IDCMPWindow == win)
  856.       {
  857.          Remove(msg);
  858.          ReplyMsg(msg);
  859.       }
  860.       msg = (struct IntuiMessage *)succ;
  861.    }
  862. }
  863.